package org.springblade.metadata.app;

import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.google.gson.Gson;
import com.raysdata.atlas.common.SystemConstant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.atlas.AtlasServiceException;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.api.ResultCode;
import org.springblade.metadata.dto.EntityDTO;
import org.springblade.metadata.entity.Category;
import org.springblade.metadata.service.FTPFileWriter;
import org.springblade.metadata.service.ICategoryService;
import org.springblade.metadata.service.TypeSystemService;
import org.springblade.metadata.service.impl.EntityService;
import org.springblade.metadata.service.impl.GossaryService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@NonDS
@RestController
@RequiredArgsConstructor
@RequestMapping("v2/fileentity")
@Slf4j
@Api(value = "fileentity", tags = "fileentity")
public class FileEntityController extends BladeController {

	private final ICategoryService categoryService;

	private final TypeSystemService typeSystemService;

	private final EntityService entityService;

	private final GossaryService gossaryService;

	private final FTPFileWriter ftpFileWriter;
	@Value("${fileTask.targetPath}")
	private String targetPath;
	@Value("${fileTask.dataSourceId}")
	private Integer dataSourceId;
	@Value("${fileTask.dataTargetId}")
	private Integer dataTargetId;

	@Value("${phinscheduler.host}")
	private String host;

	@Value("${phinscheduler.api.process_save}")
	private String uri;

	@PostMapping("/save")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "新增", notes = "传入EntityDTO   ")
	public R submit(@RequestPart("file") MultipartFile file, String json) throws IOException {
		if(file.isEmpty()){
			return R.fail(ResultCode.PARAM_MISS, "请选择需要上传的文件");
		}
		EntityDTO dto = new Gson().fromJson(json, EntityDTO.class);

		//修改文件名称
		String fileName = file.getOriginalFilename();
		//保存原文件名
		dto.getEntity().getEntity().getAttributes().put("FILENAME", fileName);
		if (fileName.indexOf(".") != -1) {
			String fileType=fileName.substring(fileName.lastIndexOf("."));
			fileName = System.currentTimeMillis() + fileType;

		}
		String tmpDir = ftpFileWriter.saveFile(file.getInputStream(), fileName, false);
		//保存最新路径
		dto.getEntity().getEntity().getAttributes().put("FILEPATH", targetPath + fileName);
		if(tmpDir == null){
			return fail("上传文件失败");
		}
		if (dto.getCategoryId() == null) {
			return R.fail(ResultCode.PARAM_MISS, "categoryId");
		}

		Category c = categoryService.getById(dto.getCategoryId());
		if (null == c) {
			return R.fail(ResultCode.PARAM_VALID_ERROR);
		}

		AtlasEntityWithExtInfo e = dto.getEntity();

		String type = e.getEntity().getTypeName();
		if (StringUtils.isBlank(type)) {
			return R.fail(ResultCode.PARAM_MISS, "type");
		}

		AtlasEntityDef def = typeSystemService.getEntityByName(type);

		if (def == null) {
			return R.fail(ResultCode.PARAM_MISS, "type");
		}

		try {

			AtlasEntityWithExtInfo we = dto.getEntity();

			Map<String, String> cas = we.getEntity().getCustomAttributes();
			if(cas == null) {
				cas = new HashMap<>();
			}
			if(StringUtils.isNotEmpty(dto.getGrade())) {
				cas.put(SystemConstant.USER_DEFINED_GRADE, dto.getGrade());
			}
			BladeUser user = getUser();
			if(user!=null) {
				cas.put(SystemConstant.USER_DEFINED_USERID, user.getUserId().toString());
				cas.put(SystemConstant.USER_DEFINED_USERNAME, user.getUserName());
				we.getEntity().setCreatedBy(user.getUserName());
			}
			
			we.getEntity().setCustomAttributes(cas);
			AtlasEntity res = entityService.save(we);
			if (res == null) {
				if(StringUtils.isNotEmpty(we.getEntity().getGuid())&&!we.getEntity().getGuid().equals("-1")) {
					log.info("no update {}",we.toString());
				}else {
					return R.fail(ResultCode.FAILURE, we.toString());
				}
				entityService.setLable(we.getEntity().getGuid(), we.getEntity().getLabels());
				return R.data(entityService.get(we.getEntity().getGuid()));
			}else {
				
				String termId = gossaryService.getGuidByCategaryid(c);
				
				gossaryService.assignTermToEntities(termId, res.getGuid());
			}
            

			if(CollectionUtils.isNotEmpty(dto.getLables())) {
				entityService.addLable(res.getGuid(), dto.getLables());
			}
			String name = String.valueOf(dto.getEntity().getEntity().getAttributes().get("FILENAME"));
			if(!createTask(tmpDir, name)){
				return fail("创建任务失败");
			}
			return R.data(entityService.get(res.getGuid()));

		} catch (AtlasServiceException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return R.fail(ResultCode.FAILURE,e1.getMessage());
		}
	}
	/**
	 * @Author sdw
	 * @Description ssssasd
	 * @Date 2021/7/15
	 * @Param [tmpDir]
	 * @return boolean
	**/
	private boolean createTask(String tmpDir, String fileName){
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		headers.set("Blade-Auth", getRequest().getHeader("Blade-Auth"));
		headers.set("Authorization", getRequest().getHeader("Authorization"));
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		MultiValueMap map = new LinkedMultiValueMap();
		String name = "文件数据[" + fileName + "]入库任务" + System.currentTimeMillis();
		String desc = "系统自动创建的文件数据入库任务";
		map.add("name", name);
		String format = "{\"timeout\":0,\"tenantId\":%d,\"tasks\":[{\"conditionResult\":{\"failedNode\":[],\"successNode\":[]},\"dependence\":{},\"maxRetryTimes\":\"0\",\"preTasks\":[],\"retryInterval\":\"1\",\"runFlag\":\"NORMAL\",\"taskInstancePriority\":\"MEDIUM\",\"timeout\":{\"enable\":false,\"strategy\":\"\"},\"type\":\"DATAX\",\"workerGroup\":\"default\",\"description\":\"%s\",\"id\":\"%s\",\"name\":\"%s\",\"params\":{\"customConfig\":0,\"dataSource\":%d,\"dataTarget\":%d,\"dsType\":\"FTP\",\"dtType\":\"FTP\",\"jobSpeedByte\":0,\"jobSpeedRecord\":1000,\"postStatements\":[],\"preStatements\":[],\"sourceCloumns\":[],\"sourcePath\":\"%s\",\"sourceTable\":\"\",\"targetCloumns\":[],\"targetPath\": \"%s\",\"targetTable\":\"\",\"where\":\"\"}}]}";
		String json = String.format(format, getUser().getTenantId(), desc, UUID.randomUUID().toString(), name, dataSourceId, dataTargetId, tmpDir, targetPath);
		map.add("processDefinitionJson", json);
		map.add("locations", "{}");
		map.add("connects", "[]");
		map.add("type", "2");
		map.add("description", desc);
		HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity(map, headers);
		ResponseEntity<String> responseEntity = new RestTemplate().exchange(host + uri, HttpMethod.POST, requestEntity, String.class);
		JSONObject ret = JSONObject.parseObject(responseEntity.getBody());
		String code = ret.getString("code");
		return "0".equals(code) ? true : false;
	}

}
